//
// Created by gogoqiu on 2021/9/1.
//

#include "ProgressDialog.h"



//#define wxDEFINE_EVENT( name, type ) \
//        const wxEventTypeTag< type > name( wxNewEventType() )
wxDEFINE_EVENT(wxEVT_COMMAND_PROGRESSTHREAD_COMPLETED, wxThreadEvent);//定义事件种类
wxDEFINE_EVENT(wxEVT_COMMAND_PROGRESSTHREAD_UPDATE, wxThreadEvent);


wxBEGIN_EVENT_TABLE(ProgressDialog, wxDialog)
                //EVT_CLOSE(MyFrame::OnClose)
                //EVT_MENU(Minimal_Start, MyFrame::DoStartThread)
                EVT_COMMAND(wxID_ANY, wxEVT_COMMAND_PROGRESSTHREAD_UPDATE, ProgressDialog::OnThreadUpdate)
                EVT_COMMAND(wxID_ANY, wxEVT_COMMAND_PROGRESSTHREAD_COMPLETED, ProgressDialog::OnThreadCompletion)
wxEND_EVENT_TABLE()

wxThread::ExitCode ProgressThread::Entry()
{
    if (!TestDestroy())
    {
        // ... 干一些事情...
        //
        //wxQueueEvent(m_pHandler, new wxThreadEvent(wxEVT_COMMAND_PROGRESSTHREAD_UPDATE));//发送事件
        SendMsgToDialog(wxEVT_COMMAND_PROGRESSTHREAD_UPDATE, wxT("Thread is running!"));
    }

    //通知事件句柄这个线程将会被销毁。注意：这里我们假定使用m_pHandler是安全的
    //（在这种情况下这将由MyFrame的析构函数确保）
    //wxQueueEvent(m_pHandler, new wxThreadEvent(wxEVT_COMMAND_PROGRESSTHREAD_COMPLETED));//发送事件
    SendMsgToDialog(wxEVT_COMMAND_PROGRESSTHREAD_COMPLETED, wxT("Thread is over!"));
    return (wxThread::ExitCode)0; // 成功
}

void ProgressThread::SendMsgToDialog(const wxEventType & evtType,const wxString& msg) {
    auto *threadEvt = new wxThreadEvent(evtType);
    auto *threadMsg = new THREAD_MSG_TYPE{wxThread::GetCurrentId(), msg};
    threadEvt->SetExtraLong(reinterpret_cast<long>(threadMsg));
    wxQueueEvent(m_pHandler, threadEvt);
}

ProgressThread::~ProgressThread()
{
    wxCriticalSectionLocker enter(m_pHandler->m_pThreadCS);
    //线程正在被销毁，确保不要调用了无效的指针
    m_pHandler->m_pThread = nullptr;
    printf("~ProgressThread");
}

/*
 * 时钟
 * 线程
 */
ProgressDialog::ProgressDialog(wxWindow *parent, wxWindowID id)
        :wxDialog(parent, wxID_ANY, "Progress" ){
    Center();
    DoStartThread();
}

void ProgressDialog::DoStartThread()
{
    //
    m_pThread = new ProgressThread(this);
    if ( m_pThread->Run() != wxTHREAD_NO_ERROR )
    {
        wxLogError("Can't create the thread!");
        delete m_pThread;
        m_pThread = nullptr;
    }
    //在调用wxThread::Run()之后，指针m_pThread是不安全的：
    //在任何时候线程都有可能结束（因为它完成了自己的工作）
    //为了避免调用无效的指针，在线程结束时OnThreadExit()中将会把指针赋值为空。
    //Bind(wxEVT_COMMAND_PROGRESSTHREAD_COMPLETED, &ProgressDialog::OnThreadCompletion, this, wxID_ANY );
    //Bind(wxEVT_COMMAND_PROGRESSTHREAD_UPDATE, &ProgressDialog::OnThreadUpdate, this, wxID_ANY );
}

void ProgressDialog::OnThreadCompletion(wxCommandEvent& event)
{
    wxMessageOutputDebug().Printf("GitAllDialog: MyThread exited!\n");
}

//void ProgressDialog::OnThreadUpdate(wxThreadEvent& event)
void ProgressDialog::OnThreadUpdate(wxCommandEvent& event)
{
    wxMessageOutputDebug().Printf("GitAllDialog: MyThread update...\n");
    wxThreadEvent* tEvt = (wxThreadEvent*)&event;
    THREAD_MSG_TYPE * threadMsg = (THREAD_MSG_TYPE *)tEvt->GetExtraLong();
    //wxString msg = wxString::Format(wxT("线程Id:%x，发来消息：%s\r\n"), threadMsg->threadId, threadMsg->info);
    //printf( "%s\n", msg.t_str());
    //delete threadMsg;
}

void ProgressDialog::DoPauseThread()
{

    //任何时候我们访问m_pThread时必须先确认在此期间它不会被修改；由于一个单独线程在给出时位于一个
    //安全区域，所以下面的代码是安全的。
    wxCriticalSectionLocker enter(m_pThreadCS);
    if (m_pThread) // 线程仍旧存在？
    {
        //不在安全区域，一旦到达这里，下列情况可能会发生：系统调度把控制权给MyThread::Entry()，
        //而这时候线程可能会因为完成了处理而使指针无效

        if (m_pThread->Pause() != wxTHREAD_NO_ERROR )

            wxLogError("Can't pause the thread!");
    }
}

void ProgressDialog::DoResumeThread(){

}

void ProgressDialog::OnClose(wxCloseEvent&)
{
    {
        wxCriticalSectionLocker enter(m_pThreadCS);
        if (m_pThread) // 线程仍旧存在？
        {
            wxMessageOutputDebug().Printf("MYFRAME: deleting thread");
            if (m_pThread->Delete() != wxTHREAD_NO_ERROR )
                wxLogError("Can't delete the thread!");
        }
    }
    //离开安全区域来给线程进入析构函数的可能（安全区域保护m_pThreadCS）
    while (true)
    {
        { // 析构函数执行了吗？
            wxCriticalSectionLocker enter(m_pThreadCS);
            if (!m_pThread)
                break;
        }
        // wait for thread completion
        wxThread::This()->Sleep(1);
    }
    Destroy();
}

ProgressDialog::~ProgressDialog() {

}
